home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Tools & Apps / Graphics & Imaging / Ultra Dragging 1.0ß1 / UOffscreenManager.inc1.p < prev    next >
Encoding:
Text File  |  1991-04-02  |  23.6 KB  |  848 lines  |  [TEXT/MPS ]

  1. { UOffscreenManager.inc1.p}
  2. { Copyright © 1990 by Apple Computer, Inc. All rights reserved.}
  3.  
  4. {    Change List:
  5.  
  6.         ddmmyy
  7.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  8.                 error in TOffscreenManager.Draw>DrawEach.
  9.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  10.                 error in TOffscreenManager.CopyBitsFrom>CopyEach.
  11.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  12.                 error in TOffscreenManager.CopyBitsFromScreen>CopyEach.
  13.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  14.                 error in TOffscreenManager.CopyBitsTo>CopyEach.
  15.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  16.                 error in TOffscreenManager.CopyBitsToScreen>CopyEach.
  17.     GAP    070990    Eliminated 2 unsafe use of an object field as a var or > 4 byte parameter
  18.                 errors in TOffscreenDevice.Draw.
  19.     GAP 070990    Eliminated unsafe use of an object field as a var or > 4 byte parameter
  20.                 error in TOffscreenDevice.CopyBitsFrom.
  21.     GAP    070990    Eliminated 4 unsafe use of an object field as a var or > 4 byte parameter
  22.                 errors in TOffscreenDevice.CopyBitsFromScreen.
  23.     GAP    070990    Eliminated 2 unsafe use of an object field as a var or > 4 byte parameter
  24.                 errors in TOffscreenDevice.CopyBitsToScreen.
  25.     GAP    191290    Added comments, cleaned up formatting, removed previous "GAP" comments.
  26.     GAP    250191    Removed superfluous comments.
  27.     GAP    250191    Added private cohandler class TDepthAndColorChecker.
  28.     GAP    250191    Added code to TOffscreenManager- IOffscreenManager, Free, Fields to
  29.                 handle fDepthAndColorChecker instance variable.
  30.     GAP    250191    Got rid of, now obslolete, TOffscreenManager.Update.
  31.     GAP    250191    Changed TOffscreenDevice.CheckDepthAndColor so warning
  32.                 concerning failure of ReallocOSImage is only written if
  33.                 we actually try to Realloc.
  34.     GAP    060291    Added code to TOffscreenDevice.CheckDepthAndColor to adjust coordinate
  35.                 system of the TOffscreenDevice so it is updated in the context of its
  36.                 on-screen graphics device.
  37.     GAP    080391    Put GetOSGrafEnv/SetOSGrafEnv/SetGrafEnv in TOffscreenDevice.CheckDepthAndColor.
  38.     GAP    010491    Some reformatting.
  39.  
  40.     End Change List. }
  41.  
  42. TYPE
  43.  
  44. {    TDepthAndColorChecker is a cohandler that checks and, if necessary, adjusts
  45.     offscreen devices for depth and color table changes every 1/2 second.            }
  46.  
  47.     TDepthAndColorChecker = OBJECT(TEvtHandler)
  48.     
  49.         fOffscreenManager: TOffscreenManager;
  50.  
  51.         PROCEDURE TDepthAndColorChecker.IDepthAndColorChecker (anOffscreenManager: TOffscreenManager);
  52.         
  53.         PROCEDURE TDepthAndColorChecker.Fields (PROCEDURE DoToField (fieldName: Str255;
  54.                                                                      fieldAddr: Ptr;
  55.                                                                      fieldType: INTEGER));
  56.         OVERRIDE;
  57.         
  58.         FUNCTION TDepthAndColorChecker.DoIdle(phase: IdlePhase): BOOLEAN;
  59.         OVERRIDE;
  60.         
  61.     END; {TDepthAndColorChecker}
  62.     
  63.  
  64. {    A TOffscreenDevice represents an offscreen image for every graphics
  65.     device (monitor) in the user's system.                                        }
  66.     
  67.     TOffscreenDevice = OBJECT(TOSImage)
  68.  
  69.         fParentDevice: GDHandle;    { The graphics device.                                                    }
  70.         fDeviceRect: Rect;            { The rectangle encompassing the device's screen coordinates.            }
  71.         fClipRect: Rect;            { The rectangle representing the area actually used on this OSImage.    }
  72.  
  73.         PROCEDURE TOffscreenDevice.IOffscreenDevice (gp: GrafPtr;
  74.                                                      size: Point;
  75.                                                      aScreenDevice: GDHandle);
  76.                                                      
  77.         PROCEDURE TOffscreenDevice.Fields (PROCEDURE DoToField (fieldName: Str255;
  78.                                                                 fieldAddr: Ptr;
  79.                                                                 fieldType: INTEGER));
  80.         OVERRIDE;
  81.         
  82.         PROCEDURE TOffscreenDevice.CheckDepthAndColor;
  83.         
  84.         PROCEDURE TOffscreenDevice.Draw (PROCEDURE QuickDrawStuff; drawRect: Rect);
  85.         
  86.         PROCEDURE TOffscreenDevice.CopyBitsFrom (srcBits: BitMap;
  87.                                                  srcRect: Rect;
  88.                                                  offscreenRect: Rect;
  89.                                                  mode: INTEGER;
  90.                                                  maskRgn: RgnHandle);
  91.                                                  
  92.         PROCEDURE TOffscreenDevice.CopyBitsFromScreen (screenRect: Rect;
  93.                                                        mode: INTEGER;
  94.                                                        maskRgn: RgnHandle);
  95.                                                        
  96.         PROCEDURE TOffscreenDevice.CopyBitsTo (dstBits: BitMap;
  97.                                                dstRect: Rect;
  98.                                                offscreenRect: Rect;
  99.                                                mode: INTEGER;
  100.                                                maskRgn: RgnHandle);
  101.                                                
  102.         PROCEDURE TOffscreenDevice.CopyBitsToScreen (screenRect: Rect;
  103.                                                      mode: INTEGER;
  104.                                                      maskRgn: RgnHandle);
  105.  
  106.     END; {TOffscreenDevice}
  107.  
  108.  
  109. {    Data structure representing a 2-D transformation.    }
  110.  
  111.     TransformRect = RECORD
  112.             CASE INTEGER OF
  113.                 0: (
  114.                         offsetV: INTEGER;
  115.                         offsetH: INTEGER;
  116.                         scaleV: INTEGER;
  117.                         scaleH: INTEGER
  118.                 );
  119.  
  120.                 1: (
  121.                         offset: Point;
  122.                         scale: Point
  123.                 );
  124.     END;
  125.  
  126.  
  127. {    CalculateTransform will calculate a TransformRect (with translation and scaling)
  128.     that will ransform the 'target' rectangle to the 'std' rectangle when the
  129.     Transform procedure is used.                                                        }
  130.  
  131. PROCEDURE CalculateTransform (target, std: Rect;
  132.                               VAR transform: TransformRect);
  133.  
  134.     VAR
  135.     
  136.         targetDeltaH, targetDeltaV: INTEGER;
  137.         stdDeltaH, stdDeltaV: INTEGER;
  138.  
  139.     BEGIN {CalculateTransform}
  140.         targetDeltaH := target.right - target.left;
  141.         targetDeltaV := target.bottom - target.top;
  142.         stdDeltaH := std.right - std.left;
  143.         stdDeltaV := std.bottom - std.top;
  144.     
  145.         transform.scaleH := stdDeltaH DIV targetDeltaH;
  146.         transform.scaleV := stdDeltaV DIV targetDeltaV;
  147.         transform.offsetH := std.left - target.left;
  148.         transform.offsetV := std.top - target.top
  149.     END; {CalculateTransform}
  150.  
  151.  
  152. {    Transform will apply the transform in the TransformRect, 'using', to the 'fromRect'
  153.     to produce the 'toRect'.  That is, T(fromRect) = toRect.                                }
  154.  
  155. PROCEDURE Transform (fromRect: Rect;
  156.                      using: TransformRect;
  157.                      VAR toRect: Rect);
  158.  
  159.     BEGIN {Transform}
  160.         toRect.left := (fromRect.left + using.offsetH) * using.scaleH;
  161.         toRect.right := (fromRect.right + using.offsetH) * using.scaleH;
  162.         toRect.top := (fromRect.top + using.offsetV) * using.scaleV;
  163.         toRect.bottom := (fromRect.bottom + using.offsetV) * using.scaleV
  164.     END; {Transform}
  165.  
  166.  
  167. {::::::::::::::::: TDepthAndColorChecker :::::::::::::::::::}
  168.  
  169. PROCEDURE TDepthAndColorChecker.IDepthAndColorChecker (anOffscreenManager: TOffscreenManager);
  170.  
  171.     CONST
  172.         kIdleFreq = 30;    { Every 1/2 second }
  173.  
  174.     BEGIN {TDepthAndColorChecker.IDepthAndColorChecker}
  175.         fOffscreenManager := anOffscreenManager;
  176.         SELF.IEvtHandler(NIL);
  177.         SELF.SetIdleFreq(kIdleFreq)
  178.     END; {TDepthAndColorChecker.IDepthAndColorChecker}
  179.     
  180.     
  181. PROCEDURE TDepthAndColorChecker.Fields (PROCEDURE DoToField (fieldName: Str255;
  182.                                                              fieldAddr: Ptr;
  183.                                                              fieldType: INTEGER));
  184. OVERRIDE;
  185.  
  186.     BEGIN {TDepthAndColorChecker.Fields}
  187.         DoToField('TDepthAndColorChecker', NIL, bClass);
  188.         DoToField('fOffscreenManager', @fOffscreenManager, bObject);
  189.         INHERITED Fields(DoToField);
  190.     END;{TDepthAndColorChecker.Fields}
  191.  
  192.  
  193. FUNCTION TDepthAndColorChecker.DoIdle(phase: IdlePhase): BOOLEAN;
  194. OVERRIDE;
  195.  
  196.     BEGIN {TDepthAndColorChecker.DoIdle}
  197.         fOffscreenManager.CheckDepthAndColor;
  198.         DoIdle := FALSE        
  199.     END;{TDepthAndColorChecker.DoIdle}
  200.  
  201.  
  202. {::::::::::::::::: TOffscreenManager :::::::::::::::::::}
  203.  
  204. {$S AInit}
  205. PROCEDURE TOffscreenManager.IOffscreenManager (size: Point);
  206.  
  207.     VAR
  208.     
  209.         aDepthAndColorChecker: TDepthandColorChecker;
  210.         aList: TList;
  211.         port: GrafPtr;
  212.         grayRgn, portRgn: RgnHandle;
  213.         aGDevice: GDHandle;
  214.         anOffscreenDevice: TOffscreenDevice;
  215.  
  216.     BEGIN {TOffscreenManager.IOffscreenManager}
  217.     
  218.     {    Initialize the instance variables    }
  219.         fDepthAndColorChecker := NIL;
  220.         fDesktopPort := NIL;
  221.         fScreenRect.topLeft := gZeroPt;
  222.         fScreenRect.botRight := size;
  223.     
  224.         fList := NIL;
  225.         NEW(aList);
  226.         FailNIL(aList);
  227.         aList.IList;
  228.     
  229.     {$IFC qDebug}
  230.         aList.SetEltType('TOffscreenDevice');
  231.     {$ENDC}
  232.     
  233.         fList := aLIst;
  234.     
  235.     {    Make a GrafPort that encompasses all screens - see Tech Note #194    }
  236.     
  237.         IF colorQD THEN        { Color }
  238.             BEGIN
  239.                 port := GrafPtr(NewPtr(SIZEOF(CGrafPort)));
  240.                 FailNIL(port);
  241.                 OpenCPort(CGrafPtr(port))
  242.             END
  243.         ELSE                { B&W }
  244.             BEGIN
  245.                 port := GrafPtr(NewPtr(SIZEOF(GrafPort)));
  246.                 FailNIL(port);
  247.                 OpenPort(port)
  248.             END;
  249.     
  250.         grayRgn := GetGrayRgn;        { Get the desktop "gray" region.                    }
  251.         portRgn := NewRgn;            { Make the visible region a copy of GrayRgn and its    }
  252.         CopyRgn(grayRgn, portRgn);    { bounding box the portRect.                        }
  253.         port^.visRgn := portRgn;
  254.         port^.portRect := portRgn^^.rgnBBox;
  255.         fDesktopPort := GrafPtr(port);
  256.     
  257.     {    Create and store in fList an offscreen GDevice for every screen    }
  258.     
  259.         IF colorPort(port) THEN        { Color }
  260.             BEGIN
  261.                 aGDevice := GetDeviceList;
  262.                 REPEAT
  263.                     NEW(anOffscreenDevice);
  264.                     FailNIL(anOffscreenDevice);
  265.                     anOffscreenDevice.IOffScreenDevice(port, size, aGDevice);
  266.                     fList.Insert(anOffscreenDevice);
  267.                     aGDevice := GetNextDevice(aGDevice)
  268.                 UNTIL aGDevice = NIL
  269.             END
  270.         ELSE                        { B&W }
  271.             BEGIN
  272.                 NEW(anOffscreenDevice);
  273.                 FailNIL(anOffscreenDevice);
  274.                 anOffscreenDevice.IOffScreenDevice(GrafPtr(port), size, NIL);
  275.                 fList.Insert(anOffscreenDevice);
  276.             END;
  277.             
  278.     {    Create and install a cohandler to periodically adjust color and depth. }
  279.     
  280.         NEW(aDepthAndColorChecker);
  281.         FailNIL(aDepthAndColorChecker);
  282.         aDepthAndColorChecker.IDepthAndColorChecker(SELF);
  283.         gApplication.InstallCohandler(aDepthAndColorChecker, TRUE);
  284.         fDepthAndColorChecker := aDepthAndColorChecker;
  285.     
  286.     END; {TOffscreenManager.IOffscreenManager}
  287.     
  288.  
  289. {$S AInit}
  290. PROCEDURE TOffscreenManager.Free;
  291. OVERRIDE;
  292.  
  293.     BEGIN {TOffscreenManager.Free}
  294.  
  295.     {    Free associated cohandler    }
  296.         IF fDepthAndColorChecker <> NIL THEN
  297.             BEGIN
  298.  
  299.             {    Remove from cohandler chain and free.    }
  300.             
  301.                 gApplication.InstallCohandler(fDepthAndColorChecker, FALSE);
  302.                 FreeIfObject(fDepthAndColorChecker);
  303.                 
  304.             END;
  305.  
  306.     {     Free the grafport representing the desktop.    }
  307.         IF fDesktopPort <> NIL THEN
  308.             BEGIN
  309.                 ClosePort(fDesktopPort);
  310.                 DisposPtr(Ptr(fDesktopPort))
  311.             END;
  312.  
  313.     {    Free the list and all its TOffscreenDevices.    }
  314.         IF fList <> NIL THEN
  315.             fList.FreeList
  316.             
  317.     END; {TOffscreenManager.Free}
  318.  
  319.  
  320. {$S AFields}
  321. PROCEDURE TOffscreenManager.Fields (PROCEDURE DoToField (fieldName: Str255;
  322.                                                          fieldAddr: Ptr;
  323.                                                          fieldType: INTEGER));
  324. OVERRIDE;
  325.  
  326.     BEGIN {TOffscreenManager.Fields}
  327.         DoToField('TOffscreenManager', NIL, bClass);
  328.         DoToField('fDepthAndColorChecker', @fDepthAndColorChecker, bObject);
  329.         DoToField('fDesktopPort', @fDesktopPort, bGrafPtr);
  330.         DoToField('fScreenRect', @fScreenRect, bRect);
  331.         DoToField('fList', @fList, bObject);
  332.         INHERITED Fields(DoToField);
  333.     END;{TOffscreenManager.Fields}
  334.  
  335.  
  336. {$S ARes}
  337. PROCEDURE TOffscreenManager.CheckDepthAndColor;
  338.  
  339.     PROCEDURE CheckEach (item: TOffscreenDevice);
  340.  
  341.         BEGIN {CheckEach}
  342.             item.CheckDepthAndColor
  343.         END; {CheckEach}
  344.  
  345.     BEGIN {TOffscreenManager.CheckDepthAndColor}
  346.         fList.Each(CheckEach)
  347.     END; {TOffscreenManager.CheckDepthAndColor}
  348.  
  349.  
  350. {$S ADoCommand}
  351. PROCEDURE TOffscreenManager.Draw (PROCEDURE QuickDrawStuff);
  352.  
  353. {    This procedure takes a procedure as a parameter that has Quickdraw calls and
  354.     executes that procedure in the context of every TOffscreenDevice.  The
  355.     TOffscreenDevice can tell whether it needs to do anything by checking to
  356.     see if screenRect intersects it dstRect.                                        }
  357.  
  358.     PROCEDURE DrawEach (item: TOffscreenDevice);
  359.     
  360.         VAR
  361.             screenRect: Rect;
  362.  
  363.         BEGIN {DrawEach}
  364.             screenRect := fScreenRect;
  365.             item.Draw(QuickDrawStuff, screenRect)
  366.         END; {DrawEach}
  367.  
  368.     BEGIN {TOffscreenManager.Draw}
  369.         fList.Each(DrawEach)
  370.     END; {TOffscreenManager.Draw}
  371.  
  372.  
  373. {$S ADoCommand}
  374. PROCEDURE TOffscreenManager.CopyBitsFrom (srcBits: BitMap;
  375.                                           srcRect: Rect;
  376.                                           offscreenRect: Rect;
  377.                                           mode: INTEGER;
  378.                                           maskRgn: RgnHandle);
  379.  
  380. {    Do a CopyBits from srcBits using sectSrcRect to each appropriate TOffscreenDevice.
  381.     A transform is used to map that part of the source that corresponds to the clipped
  382.     portion of the offscreenRect that is in this TOffscreenDevice.  That is,
  383.     
  384.         offscreenRect                sectScreenRect
  385.         _____________        =        ______________
  386.         srcRect                        sectSrcRect
  387.         
  388.     where offscreenRect, srcRect, and sectScreenRect are given and sectSrcRect
  389.     needs to be calculated using the transformation.                                        }
  390.  
  391.     VAR
  392.         aTransformRect: TransformRect;
  393.  
  394.     PROCEDURE CopyEach (item: TOffscreenDevice);
  395.  
  396.         VAR
  397.             clipRect, sectScreenRect, sectSrcRect: Rect;
  398.  
  399.         BEGIN {CopyEach}
  400.  
  401.             clipRect := item.fClipRect;
  402.  
  403.         {    Find the intersection of the offscreenRect and that part of the
  404.             TOffscreenDevice that is used.    If they intersect do the CopyBits.    }
  405.  
  406.             IF SectRect(clipRect, offscreenRect, sectScreenRect) THEN
  407.                 BEGIN
  408.  
  409.                 {    Calculate sectSrcRect, that part of the source that is
  410.                     actually used in the CopyBits.                                }
  411.             
  412.                     Transform(sectScreenRect, aTransformRect, sectSrcRect);
  413.                     
  414.                 {    Do the CopyBits.    }
  415.                 
  416.                     item.CopyBitsFrom(srcBits, sectSrcRect, sectScreenRect, mode, maskRgn)
  417.                     
  418.                 END
  419.                 
  420.         END; {CopyEach}
  421.  
  422.     BEGIN {TOffscreenManager.CopyBitsFrom}
  423.  
  424.     {    Create a transform that transforms from the offscreenRect to the srcRect.    }
  425.         CalculateTransform(offscreenRect, srcRect, aTransformRect);
  426.  
  427.     {    Do a CopyBits for each TOffscreenDevice.    }
  428.         fList.Each(CopyEach)
  429.         
  430.     END; {TOffscreenManager.CopyBitsFrom}
  431.  
  432.  
  433. {$S ADoCommand}
  434. PROCEDURE TOffscreenManager.CopyBitsFromScreen (screenRect: Rect;
  435.                                                 mode: INTEGER;
  436.                                                 maskRgn: RgnHandle);
  437.  
  438. {    Do a CopyBits from the screen using screenRect as the source
  439.     rectangle to each appropriate TOffscreenDevice.  This also
  440.     sets the new fScreenRect to be screenRect, in effect, this
  441.     signals we are "mirroring" a new part of the screen.            }
  442.  
  443.     PROCEDURE CopyEach (item: TOffscreenDevice);
  444.  
  445.         VAR
  446.             screenRect: Rect;
  447.  
  448.         BEGIN {CopyEach}
  449.             screenRect := fScreenRect;
  450.             item.CopyBitsFromScreen(screenRect, mode, maskRgn)
  451.         END; {CopyEach}
  452.  
  453.     BEGIN {TOffscreenManager.CopyBitsFromScreen}
  454.         fScreenRect := screenRect;    { Signals a mirroring of another area of screen. }
  455.         fList.Each(CopyEach)
  456.     END; {TOffscreenManager.CopyBitsFromScreen}
  457.  
  458.  
  459. {$S ADoCommand}
  460. PROCEDURE TOffscreenManager.CopyBitsTo (dstBits: BitMap;
  461.                                         dstRect: Rect;
  462.                                         offscreenRect: Rect;
  463.                                         mode: INTEGER;
  464.                                         maskRgn: RgnHandle);
  465.  
  466. {    Do a CopyBits from each appropriate TOffscreenDevice to dstBits using sectDstRect.
  467.     A transform is used to map that part of the destination that corresponds to the clipped
  468.     portion of the offscreenRect that is in this TOffscreenDevice.  That is,
  469.     
  470.         offscreenRect                sectScreenRect
  471.         _____________        =        ______________
  472.         dstRect                        sectDstRect
  473.         
  474.     where offscreenRect, dstRect, and sectScreenRect are given and sectDstRect
  475.     needs to be calculated using the transformation.                                        }
  476.  
  477.     VAR
  478.         aTransformRect: TransformRect;
  479.  
  480.     PROCEDURE CopyEach (item: TOffscreenDevice);
  481.  
  482.         VAR
  483.             clipRect, sectScreenRect, sectDstRect: Rect;
  484.  
  485.         BEGIN {CopyEach}
  486.  
  487.             clipRect := item.fClipRect;
  488.  
  489.         {    Find the intersection of the offscreenRect and that part of the
  490.             TOffscreenDevice that is used.    If they intersect do the CopyBits.    }
  491.  
  492.             IF SectRect(clipRect, offscreenRect, sectScreenRect) THEN
  493.                 BEGIN
  494.  
  495.                 {    Calculate sectDstRect, that part of the destination that is
  496.                     actually used in the CopyBits.                                }
  497.             
  498.                     Transform(sectScreenRect, aTransformRect, sectDstRect);
  499.                     
  500.                 {    Do the CopyBits.    }
  501.                 
  502.                     item.CopyBitsTo(dstBits, sectDstRect, sectScreenRect, mode, maskRgn)
  503.                     
  504.                 END
  505.                 
  506.         END; {CopyEach}
  507.  
  508.     BEGIN {TOffscreenManager.CopyBitsTo}
  509.         CalculateTransform(offscreenRect, dstRect, aTransformRect);
  510.         fList.Each(CopyEach)
  511.     END; {TOffscreenManager.CopyBitsTo}
  512.  
  513.  
  514. {$S ADoCommand}
  515. PROCEDURE TOffscreenManager.CopyBitsToScreen (mode: INTEGER; maskRgn: RgnHandle);
  516.  
  517. {    Do a CopyBits from each appropriate portion of each TOffscreenDevice
  518.     to the screen using screenRect as the source rectangle.                    }
  519.  
  520.      PROCEDURE CopyEach (item: TOffscreenDevice);
  521.  
  522.         VAR
  523.             screenRect: Rect;
  524.  
  525.         BEGIN {CopyEach}
  526.             screenRect := fScreenRect;
  527.             item.CopyBitsToScreen(screenRect, mode, maskRgn)
  528.         END; {CopyEach}
  529.  
  530.     BEGIN {TOffscreenManager.CopyBitsToScreen}
  531.         fList.Each(CopyEach)
  532.     END; {TOffscreenManager.CopyBitsToScreen}
  533.  
  534.  
  535. {::::::::::::::::: TOffscreenDevice ::::::::::::::::::::}
  536.  
  537. {$S AInit}
  538. PROCEDURE TOffscreenDevice.IOffscreenDevice (gp: GrafPtr;
  539.                                              size: Point;
  540.                                              aScreenDevice: GDHandle);
  541.  
  542.     VAR
  543.     
  544.         grayRgn: RgnHandle;
  545.         screenRect: Rect;
  546.  
  547.     BEGIN {TOffscreenDevice.IOffscreenDevice}
  548.     
  549.         fParentDevice := aScreenDevice;
  550.         IF aScreenDevice <> NIL THEN
  551.             fDeviceRect := aScreenDevice^^.gdPMap^^.bounds
  552.         ELSE
  553.             BEGIN    { No GDevices for this machine. }
  554.                 grayRgn := GetGrayRgn;
  555.                 fDeviceRect := grayRgn^^.rgnBBox
  556.             END;
  557.  
  558.     { Put in the top left of the device, for now. }
  559.         screenRect.topLeft := fDeviceRect.topLeft;
  560.     { And make the clipRect the same size, for now. }
  561.         screenRect.bottom := screenRect.top + size.v;
  562.         screenRect.right := screenRect.left + size.h;
  563.         fClipRect := screenRect;
  564.         INHERITED IOSImage(gp, screenRect)
  565.     
  566.     END; {TOffscreenDevice.IOffscreenDevice}
  567.  
  568.  
  569. {$S AFields}
  570. PROCEDURE TOffscreenDevice.Fields (PROCEDURE DoToField (fieldName: Str255;
  571.                                                         fieldAddr: Ptr;
  572.                                                         fieldType: INTEGER));
  573. OVERRIDE;
  574.  
  575.     BEGIN {TOffscreenDevice.Fields}
  576.         DoToField('TOffscreenDevice', NIL, bClass);
  577.         DoToField('fParentDevice', @fParentDevice, bHandle);
  578.         DoToField('fDeviceRect', @fDeviceRect, bRect);
  579.         DoToField('fClipRect', @fClipRect, bRect);
  580.         INHERITED Fields(DoToField);
  581.     END;{TOffscreenDevice.Fields}
  582.  
  583.  
  584. {$S ADoCommand}
  585. PROCEDURE TOffscreenDevice.CheckDepthAndColor;
  586.  
  587.     VAR
  588.  
  589.         savedPort: GrafPtr;
  590.         savedGDevice: GDHandle;
  591.         offset: Point;
  592.         deviceRect: Rect;
  593.         dstRect: Rect;
  594.         ls: BOOLEAN;
  595.         success: BOOLEAN;
  596.  
  597.     BEGIN {TOffscreenDevice.CheckDepthAndColor}
  598.     
  599.     
  600.     {    Adjust the coordinate system to reflect a portion of the
  601.         on-screen device in preparation for potential updates.
  602.         That is, make sure that the part of the screen for which
  603.         we are updating is wholly on the device that this object
  604.         is responsible for.                                             }
  605.  
  606.     {    Save the current grafEnv and set it to this offscreen    }
  607.     
  608.         GetGrafEnv(savedPort, savedGDevice);
  609.         dstRect := fDstRect;
  610.         SetOSGrafEnv(fParent, dstRect, fOSIP);
  611.         
  612.         deviceRect := fDeviceRect;
  613.         SetOrigin(deviceRect.left, deviceRect.top);
  614.  
  615.         offset.h := deviceRect.left - dstRect.left;
  616.         offset.v := deviceRect.top - dstRect.top;
  617.         OffsetRect(dstRect, offset.h, offset.v);
  618.         ClipRect(dstRect);
  619.         fClipRect := dstRect;
  620.         fDstRect := dstRect;
  621.  
  622.     {    Restore old port }
  623.     
  624.         SetGrafEnv(savedPort, savedGDevice);
  625.  
  626.     {    Adjust the color and depth.    }
  627.     
  628.     {$H-}
  629.         ls := SELF.Lock(TRUE);
  630.         IF NOT CorrectDepth(fParent, fDstRect, fOSIP) THEN
  631.             BEGIN
  632.                 success := ReallocOSImage(fParent, fDstRect, fOSIP);
  633.             
  634.             {$IFC qDebug}
  635.                 IF NOT success THEN
  636.                     WRITELN('ReallocOSImage failed in TOffscreenDevice.CheckDepthAndColor');
  637.             {$ENDC}
  638.  
  639.             END;
  640.  
  641.         IF NOT CorrectColor(fParent, fDstRect, fOSIP) THEN
  642.             RecolorOSImage(fParent, fDstRect, fOSIP);
  643.  
  644.         ls := SELF.Lock(ls)
  645.     {$H+}
  646.     
  647.     END; {TOffscreenDevice.CheckDepthAndColor}
  648.  
  649.  
  650. {$S ADoCommand}
  651. PROCEDURE TOffscreenDevice.Draw (PROCEDURE QuickDrawStuff; drawRect: Rect);
  652.  
  653. {    After checking to see if drawing needs to be done on this
  654.     TOffscreenDevice, execute QuickDrawStuff (a procedure with
  655.     Quickdraw calls) in its context.                                }
  656.  
  657.     VAR
  658.     
  659.         dstRect, dummyRect: Rect;
  660.         savedPort: GrafPtr;
  661.         savedGDevice: GDHandle;
  662.  
  663.     BEGIN {TOffscreenDevice.Draw}
  664.     
  665.     {    Check to see if this drawing is in our area before
  666.         doing anything.                                            }
  667.     
  668.         dstRect := fDstRect;
  669.         IF SectRect(drawRect, dstRect, dummyRect) THEN
  670.             BEGIN
  671.     
  672.             {    Save the current grafEnv and set it to this offscreen    }
  673.                 GetGrafEnv(savedPort, savedGDevice);
  674.                 SetOSGrafEnv(fParent, dstRect, fOSIP);
  675.     
  676.             {    Do whatever client wants in our GrafPort    }
  677.                 QuickDrawStuff;
  678.     
  679.             {    Restore old port    }
  680.                 SetGrafEnv(savedPort, savedGDevice);
  681.     
  682.             END
  683.     
  684.     END; {TOffscreenDevice.Draw}
  685.  
  686.  
  687. {$S ADoCommand}
  688. PROCEDURE TOffscreenDevice.CopyBitsFrom (srcBits: BitMap;
  689.                                          srcRect: Rect;
  690.                                          offscreenRect: Rect;
  691.                                          mode: INTEGER;
  692.                                          maskRgn: RgnHandle);
  693.  
  694. {    CopyBits from srcBits using srcRect to this device using offscreenRect.    }
  695.  
  696.     VAR
  697.     
  698.         dstRect: Rect;
  699.         savedPort: GrafPtr;
  700.         savedGDevice: GDHandle;
  701.  
  702.     BEGIN {TOffscreenDevice.CopyBitsFrom}
  703.     
  704.     {    Save the current grafEnv and set it to this offscreen    }
  705.         GetGrafEnv(savedPort, savedGDevice);
  706.         dstRect := fDstRect;
  707.         SetOSGrafEnv(fParent, dstRect, fOSIP);
  708.     
  709.     {    Blast the bits from the screen to the OSImage.    }
  710.         CopyBits(srcBits, fOSIp^.portBits, srcRect, offscreenRect, mode, maskRgn);
  711.     
  712.     {    Restore old port    }
  713.         SetGrafEnv(savedPort, savedGDevice);
  714.     
  715.     END; {TOffscreenDevice.CopyBitsFrom}
  716.  
  717.  
  718. {$S ADoCommand}
  719. PROCEDURE TOffscreenDevice.CopyBitsFromScreen (screenRect: Rect;
  720.                                                mode: INTEGER;
  721.                                                maskRgn: RgnHandle);
  722.  
  723. {    CopyBits from the screen using the intersection of our device's
  724.     rectangle and screenRect as the source rectangle.  Assumes that
  725.     the current port 'thePort' is the desktop.  Uses
  726.     TOffscreenDevice.CopyBitsFrom method.                                }
  727.  
  728.     VAR
  729.     
  730.         savedPort: GrafPtr;
  731.         savedGDevice: GDHandle;
  732.         deviceRect, dstRect, aClipRect: Rect;
  733.         screenSectRect: Rect;
  734.         newDstRect: Rect;
  735.         offset: Point;
  736.  
  737.     {$IFC qDebug}
  738.         aRect: Rect;
  739.         top, left, bottom, right: INTEGER;
  740.     {$ENDC}
  741.  
  742.     BEGIN {TOffscreenDevice.CopyBitsFromScreen}
  743.     
  744.     {    screenSectRect is that part of the screenRect that is on our device, ie.,
  745.         the intersection of the screenRect and our own device.                        }
  746.     
  747.         deviceRect := fDeviceRect;
  748.         IF SectRect(screenRect, deviceRect, screenSectRect) THEN
  749.             BEGIN
  750.     
  751.             {    Save the current grafEnv and set it to this offscreen    }
  752.     
  753.                 GetGrafEnv(savedPort, savedGDevice);
  754.                 dstRect := fDstRect;
  755.                 SetOSGrafEnv(fParent, dstRect, fOSIP);
  756.     
  757.             {    Adjust the coordinate system to properly reflect what portion
  758.                 of the screen we're mirroring.                                    }
  759.  
  760.                 SetOrigin(screenSectRect.left, screenSectRect.top);
  761.                 ClipRect(screenSectRect);
  762.                 fClipRect := screenSectRect;
  763.     
  764.                 newDstRect := fDstRect;
  765.                 offset.h := screenSectRect.left - newDstRect.left;
  766.                 offset.v := screenSectRect.top - newDstRect.top;
  767.                 OffsetRect(newDstRect, offset.h, offset.v);
  768.                 fDstRect := newDstRect;
  769.     
  770.             {    Blast the bits from the screen to the OSImage. }
  771.             
  772.                 aClipRect := fClipRect;
  773.                 SELF.CopyBitsFrom(savedPort^.portBits, screenSectRect, aClipRect, mode, maskRgn);
  774.     
  775.             { Restore old port }
  776.             
  777.                 SetGrafEnv(savedPort, savedGDevice);
  778.     
  779.             {$IFC qDebug}
  780.             {    Show what's in this offscreen in the lower-right corner of its screen. }
  781.                 IF gIntenseDebugging THEN
  782.                     BEGIN
  783.                         top := fDeviceRect.bottom - (fDstRect.bottom - fDstRect.top);
  784.                         left := fDeviceRect.right - (fDstRect.right - fDstRect.left);
  785.                         bottom := top + (fClipRect.bottom - fClipRect.top);
  786.                         right := left + (fClipRect.right - fClipRect.left);
  787.                         SetRect(aRect, left, top, right, bottom);
  788.                         CopyBits(fOSIP^.portBits, fParent^.portBits, aClipRect, aRect, mode, maskRgn);
  789.                     END;
  790.             {$ENDC}
  791.     
  792.             END
  793.             
  794.     END; {TOffscreenDevice.CopyBitsFromScreen}
  795.  
  796.  
  797. {$S ADoCommand}
  798. PROCEDURE TOffscreenDevice.CopyBitsTo (dstBits: BitMap;
  799.                                        dstRect: Rect;
  800.                                        offscreenRect: Rect;
  801.                                        mode: INTEGER;
  802.                                        maskRgn: RgnHandle);
  803.  
  804. {    CopyBits to dstBits using dstRect from this device using offscreenRect.    }
  805.  
  806.     VAR
  807.     
  808.         dstSectRect, srcSectRect: Rect;
  809.         newRect: Rect;
  810.         
  811.     BEGIN {TOffscreenDevice.CopyBitsTo}
  812.  
  813.     {    Blast the bits from the screen to the OSImage. }
  814.         CopyBits(fOSIP^.portBits, dstBits, offscreenRect, dstRect, mode, maskRgn);
  815.     
  816.     END; {TOffscreenDevice.CopyBitsTo}
  817.  
  818.  
  819. {$S ADoCommand}
  820. PROCEDURE TOffscreenDevice.CopyBitsToScreen (screenRect: Rect;
  821.                                              mode: INTEGER;
  822.                                              maskRgn: RgnHandle);
  823.  
  824. {    CopyBits to the screen using the intersection of our device's
  825.     rectangle and screenRect as the destination rectangle.  Assumes that
  826.     the current port 'thePort' is the desktop.  Uses
  827.     TOffscreenDevice.CopyBitsTo method.                                }
  828.  
  829.     VAR
  830.     
  831.         deviceRect, clipRect: Rect;
  832.         screenSectRect: Rect;
  833.         currPort: GrafPtr;
  834.         
  835.     BEGIN {TOffscreenDevice.CopyBitsToScreen}
  836.  
  837.         deviceRect := fDeviceRect;
  838.  
  839.         IF SectRect(screenRect, deviceRect, screenSectRect) THEN
  840.             BEGIN
  841.                 GetPort(currPort);
  842.         
  843.             {    Blast the bits from the OSImage to the screen. }
  844.                 clipRect := fClipRect;
  845.                 SELF.CopyBitsTo(currPort^.portBits, screenSectRect, clipRect, mode, maskRgn);
  846.             END
  847.  
  848.     END; {TOffscreenDevice.CopyBitsToScreen}